package cn.huaqingcheng.tool.data;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

/**
 * 标准分页参数接口 <br>
 * 用作参数传递时禁止为 null, 空参数应该用 {@link #empty()} 代替 <br>
 * 常用实现 {@link SimplePage}
 *
 * @see SimplePage
 * @see ReadOnlyPage
 */
@SuppressWarnings("unused")
public interface Page<T> {

    Page<?> EMPTY = new ReadOnlyPage<>();

    /**
     * 静态常量 size 100; number 1
     */
    Page<?> ALL = new ReadOnlyPage<>(100, 1);

    /**
     * 类型安全的空对象, 只读
     *
     * @see #EMPTY
     */
    @SuppressWarnings("unchecked")
    static <E> Page<E> empty() {
        return (Page<E>) EMPTY;
    }

    /**
     * 类型安全的方便的常量
     *
     * @see #ALL
     */
    @SuppressWarnings("unchecked")
    static <E> Page<E> allPage() {
        return (Page<E>) ALL;
    }

    /**
     * 页大小
     */
    Integer getSize();

    /**
     * 修改 页大小
     *
     * @throws UnsupportedOperationException 如果不支持修改
     */
    Page<T> setSize(Integer pageSize);

    /**
     * 页码
     */
    Integer getCurrent();

    /**
     * 修改 页码
     *
     * @throws UnsupportedOperationException 如果不支持修改
     */
    Page<T> setCurrent(Integer pageNumber);

    /**
     * 总记录数
     */
    Integer getTotal();

    /**
     * 修改 total
     *
     * @throws UnsupportedOperationException 如果不支持修改
     */
    Page<T> setTotal(Integer total);

    /**
     * 数据列表
     */
    List<T> getList();

    @SuppressWarnings("unchecked")
    default <R> Page<R> map(Function<? super T, ? extends R> mapper) {
        List<T> list = getList();
        if (list != null && !list.isEmpty()) {
            List<? extends R> list1 = list.stream()
                .map(mapper)
                .toList();
            setList((List<T>) list1);
        }
        return (Page<R>) this;
    }

    /**
     * 取列表第一项, 如果存在
     */
    default Optional<T> findFirst() {
        List<T> list = getList();
        if (list != null && !list.isEmpty()) {
            return Optional.ofNullable(list.get(0));
        }

        return Optional.empty();
    }

    /**
     * 重设数据列表
     *
     * @throws UnsupportedOperationException 如果不支持修改
     */
    Page<T> setList(List<T> list);

    /**
     * 如果当前类只读, 复制自身属性 以允许修改
     */
    default Page<T> copyIfReadonly(Integer total, List<T> list) {
        return copyIfReadonly().setTotal(total).setList(list);
    }

    /**
     * 如果当前类只读, 复制自身属性 以允许修改
     */
    default Page<T> copyIfReadonly() {
        return this instanceof ReadOnlyPage<T>
               ? new SimplePage<>(this)
               : this;
    }

}
